home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
program
/
progem.arc
/
gem2.asc
< prev
next >
Wrap
Text File
|
1987-10-10
|
20KB
|
417 lines
** Professional GEM **
by Tim Oren
Topic: Windows, part II
10/21/85
EXCELSIOR!
In this installment, we continue the exploration of GEM's window
manager by finding out how to process the messages received by an
application when it has a window defined on the screen.
Also, beginning with this column, sample C code demonstrating the
techniques discussed will be available on SIG*ATARI in DL5. This
will allow you to download the code without interference by the CIS
text-formatter used by ANTIC ONLINE output.
The file for this column is GEMCL2.XMO. All references to non-GEM
routines in this column refer to this file. Please note that these
files will not contain entire programs. Instead, they consist of
small pieces of utility code which you may copy and modify in your
own programs.
REDRAWING WINDOWS
One of the most misunderstood parts of GEM is the correct method for
drawing within a window. Most requests for redrawing are generated
by the GEM system, and arrive as messages (read with evnt_multi)
which contain the handle of the window, and the screen rectangle
which is "dirty" and needs to be redrawn.
Screen areas may become dirty as a result of windows being closed,
sized down, or moved, thus "exposing" an area underneath. The
completion of a dialog, or closing of a desk accessory may also free
up a screen area which needs to be redrawn. When GEM detects the
presence of a dirty rectangle, it checks its list of open windows,
and sends the application a redraw message for each of its windows
which intersects the dirty area.
CAVEAT EMPTOR
GEM does not "clip" the rectangle which it sends to the application;
that is, the rectangle may not lie entirely within the portion of
the window which is exposed on the screen. It is the job of the
application to determine in what portion of the rectangle it may
safely draw. This is done by examining the "rectangle list"
associated with the window.
A rectangle list is maintained by GEM for each active window. It
contains the portions of the window's interior which are exposed,
i.e., topmost, on the screen and within which the app may draw.
Let's consider an example to make this clear. Suppose an app has
opened two windows, and there are no desk accessory windows open. The
window which is topmost will always have only one rectangle in its
list. If the two are separate on the screen, then the second window
will also have one rectangle. If they overlap, then the top window
will "break" the rectangle of the bottom one. If the overlap is at
a corner, two rectangles will be generated for the bottom window. If
the overlap is on a side only, then three rectangles are required to
cover the exposed portion of the bottom window. Finally, if the
first window is entirely within the second, it requires four
rectangles in the list to tile the second window.
Try working out a few rectangle examples with pencil and paper to
get the feel of it. You will see that the possible combinations with
more than two windows are enormous. This, by the way, is the reason
that GEM does not send one message for each rectangle on the list:
With multiple windows, the number of messages generated would
quickly fill up the application's message queue.
Finally, note that every app MUST use this method, even if it only
uses a single window, because there may be desk accessories with
their own windows in the system at the same time. If you do not use
the rectangle lists, you may overwrite an accessory's window.
INTO THE BITS
First, we should note that the message type for a redraw request is
WM_REDRAW, which is stored in msg[0], the first location of the
message returned by evnt_multi. The window handle is stored in
msg[3]. These locations are the same for all of the message types
being discuss. The rectangle which needs to be redrawn is stored in
msg[4] through msg[7].
Now let's examine the sample redraw code in more detail. The redraw
loop is bracketed with mouse off and mouse on calls. If you forget
to do this, the mouse pointer will be over-written if it is within
the window and the next movement of the mouse will leave a
rectangular blotch on the screen as a piece of the "old" screen is
incorrectly restored.
The other necessary step is to set the window update flag. This
prevents the menu manager from dropping a menu on top of the screen
portion being redrawn. You must release this flag at the end of the
redraw, or the you will be unable to use any menus afterwards.
The window rectangles are retrieved using a get-first, get-next
scheme which will be familiar if you have used the GEM DOS or PC-DOS
wildcard file calls. The end of the rectangle list has been reached
when both the width and height returned are zero. Since some part of
a window might be off-screen (unless you have clamped its position -
see below), the retrieved rectangle is intersected with the desktop's
area, and then with the screen area for which a redraw was
requested.
Now you have the particular area of the screen in which it is legal
to draw. Unless there is only one window in your application, you
will have to test the handle in the redraw request to figure out what
to put in the rectangle.
Depending on the app, you may be drawing an AES object tree, or
executing VDI calls, or some combination of the two. In the AES
case, the computed rectangle is used to specify the bounds of the
objc_draw. For VDI work, the rectangle is used to set the clipping
area before executing the VDI calls.
A SMALL CONFESSION
At the beginning of this discussion, I deliberately omitted one
class of redraws: those initiated by the application itself.
In some cases a part of the screen must be redrawn immediately to
give feedback to the user following a keystroke, button, or mouse
action. In these cases, the application could call do_redraw
directly, without waiting for a message.
The only time you can bypass do_redraw, and draw without walking the
rectangle list, is when you can be sure that the target window is on
top, and that the figure being drawn is entirely contained within
it.
In many cases, however, an application initiated redraw happens
because of a computed change, for instance, a spreadsheet update, and
its timing is not crucial. In this instance, you may wish to have
the app send ITSELF a redraw request.
The main advantage of this approach is that the AES is smart enough
to see if there is already a redraw request for the same window in
the queue, and, if so, to merge the requests by doing a union of
their rectangles. In this fashion, the "blinky" appearance of
multiple redraws is avoided, without the need to include logic for
merging redraws within the program.
A utility routine for sending the "self-redraw" is included in the
down-load for this article.
WINDOW CONTROL REQUESTS
An application is notified by the AES, via the message system, when
the user manipulates one of the window control points. Remember that
you must have specified each control point when the window was
created, or will not receive the associated control message.
The most important thing to understand about window control is that
the change which the user requested does not take place until the
application forwards it to the AES. While this makes for a little
extra work, it gives the program a chance to intervene and validate
or modify the request to suit.
A second thing to keep in mind is that not all window updates cause a
redraw request to be generated for the window, because the AES
attempts to save time with raster moves on the screen.
Now let's look at each window control request in detail. The
message code for a window move is WM_MOVED. If you are willing to
accept any such request, just do:
wind_set(wh, WF_CXYWH, msg[4], msg[5], msg[6], msg[7]);
(Remember that wh, the window handle, is always in